package cn.edu.sgu.www.mhxysy.function.computer.score.impl;

import cn.edu.sgu.www.mhxysy.entity.equipment.Equipment;
import cn.edu.sgu.www.mhxysy.entity.equipment.EquipmentCategory;
import cn.edu.sgu.www.mhxysy.entity.equipment.EquipmentTeji;
import cn.edu.sgu.www.mhxysy.entity.equipment.EquipmentTexiao;
import cn.edu.sgu.www.mhxysy.enums.EquipmentTypes;
import cn.edu.sgu.www.mhxysy.enums.PropertyTypes;
import cn.edu.sgu.www.mhxysy.exception.GlobalException;
import cn.edu.sgu.www.mhxysy.function.computer.score.ScoreComputer;
import cn.edu.sgu.www.mhxysy.mapper.equipment.*;
import cn.edu.sgu.www.mhxysy.restful.ResponseCode;
import cn.edu.sgu.www.mhxysy.util.CollectionUtils;
import cn.edu.sgu.www.mhxysy.vo.except.AttributeVO;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.function.Predicate;

/**
 * 装备评分计算器
 * @author 沐雨橙风ιε
 * @version 1.0
 */
@Component
public class EquipmentScoreComputer implements ScoreComputer {

    /**
     * 保存装备等级-装备系数对应关系的Map集合
     */
    private final Map<Integer, Double> doubleMap;

    private final EquipmentMapper equipmentMapper;
    private final EquipmentTejiMapper equipmentTejiMapper;
    private final EquipmentTypeMapper equipmentTypeMapper;
    private final EquipmentTexiaoMapper equipmentTexiaoMapper;
    private final EquipmentCategoryMapper equipmentCategoryMapper;
    private final EquipmentAttributeMapper equipmentAttributeMapper;

    {
        doubleMap = new HashMap<>();

        doubleMap.put(60, 1.0);
        doubleMap.put(70, 4.0 / 3);
        doubleMap.put(80, 5.0 / 3);
        doubleMap.put(90, 2.0);
        doubleMap.put(100, 2.5);
    }

    @Autowired
    public EquipmentScoreComputer(
            EquipmentMapper equipmentMapper,
            EquipmentTejiMapper equipmentTejiMapper,
            EquipmentTypeMapper equipmentTypeMapper,
            EquipmentTexiaoMapper equipmentTexiaoMapper,
            EquipmentCategoryMapper equipmentCategoryMapper,
            EquipmentAttributeMapper equipmentAttributeMapper) {
        this.equipmentMapper = equipmentMapper;
        this.equipmentTejiMapper = equipmentTejiMapper;
        this.equipmentTypeMapper = equipmentTypeMapper;
        this.equipmentTexiaoMapper = equipmentTexiaoMapper;
        this.equipmentCategoryMapper = equipmentCategoryMapper;
        this.equipmentAttributeMapper = equipmentAttributeMapper;
    }

    @Override
    public Integer apply(String equipmentId) {
        Equipment equipment = equipmentMapper.selectById(equipmentId);

        if (equipment == null) {
            throw new GlobalException(ResponseCode.CONFLICT, "操作失败，装备不存在！");
        }

        /*
         * 装备评分 = 白字评分 + 绿字评分 + 蓝字评分 + 附灵评分
         *
         * ①白字属性（包含熔炼）：
         * 1、武器 = max(物理伤害, 法术伤害 × 4.45, 治疗强度 × 2.775)
         * 2、衣甲 = (物理防御 × 0.75) + (气血 × 0.21)
         * 3、头 = 物理防御 × 0.75
         * 4、项链 = (法术伤害 × 1.5) + (法术防御 × 0.75)
         * 5、腰带 = (物理防御 × 0.75) + (气血 × 0.21)
         * 6、鞋 = (速度 × 1.5) + (法术防御 × 0.75)
         *
         * ②绿字属性：绿字属性之和（含熔炼） × 1.5
         *
         * ③蓝字属性：包含特效和特技，从装备特技表、装备特效表获得
         *
         * ④附灵：90级以上武器开启附灵（武器开光）功能，开光后装备的评分会增加20
         */
        AtomicInteger score = new AtomicInteger();

        // 附灵状态为1，加20分
        if (equipment.getFulingStatus() == 1) {
            score.addAndGet(20);
        }

        // 查询装备的各项总属性
        List<AttributeVO> list = equipmentAttributeMapper.selectTotalAttributes(equipmentId);

        if(CollectionUtils.isNotEmpty(list)) {
            for (AttributeVO attribute : list) {
                // 计算附加属性的评分
                if (PropertyTypes.FJSX.getValue().equals(attribute.getPropertyType())) {
                    score.addAndGet((int) (attribute.getPropertyValue() * 1.5));
                }
            }

            // 移除附加属性
            list.removeIf(new Predicate<AttributeVO>() {
                @Override
                public boolean test(AttributeVO attribute) {
                    return PropertyTypes.FJSX.getValue().equals(attribute.getPropertyType());
                }
            });

            // 计算基础属性的评分
            Integer topType = equipmentTypeMapper.selectTopType(equipment.getCategoryId());

            score.addAndGet(computeScore(topType, list));
        }

        // 计算装备的特技、特效评分
        Integer tejiId = equipment.getTejiId();
        Integer texiaoId = equipment.getTexiaoId();

        // 获取装备类型信息
        EquipmentCategory equipmentCategory = equipmentCategoryMapper.selectById(equipment.getCategoryId());
        // 根据装备等级获取装备系数
        double coefficient = doubleMap.get(equipmentCategory.getGrade());

        if (tejiId != null && tejiId > 0) {
            EquipmentTeji equipmentTeji = equipmentTejiMapper.selectById(tejiId);

            score.addAndGet((int) (equipmentTeji.getScore() * coefficient));
        }
        if (texiaoId != null && texiaoId > 0) {
            EquipmentTexiao equipmentTexiao = equipmentTexiaoMapper.selectById(texiaoId);

            score.addAndGet((int) (equipmentTexiao.getScore() * coefficient));
        }

        return score.get();
    }

    /**
     * 计算装备/器灵的基础属性评分
     * @param type 装备类型
     * @param list 装备的白字属性列表
     * @return int 装备的属性评分
     */
    public static Integer computeScore(Integer type, List<AttributeVO> list) {
        if (CollectionUtils.isEmpty(list)) {
            return 0;
        }

        /*
         * 1、武器 = max(物理伤害, 法术伤害 × 4.45, 治疗强度 × 2.775)
         * 2、衣甲 = (物理防御 × 0.75) + (气血 × 0.21)
         * 3、头 = 物理防御 × 0.75
         * 4、项链 = (法术伤害 × 1.5) + (法术防御 × 0.75)
         * 5、腰带 = (物理防御 × 0.75) + (气血 × 0.21)
         * 6、鞋 = (速度 × 1.5) + (法术防御 × 0.75)
         */
        AtomicInteger score = new AtomicInteger();

        if (EquipmentTypes.WUQI.getValue().equals(type)) { // 武器
            List<Integer> values = new ArrayList<>();

            for (AttributeVO item : list) {
                if ("物理伤害".equals(item.getPropertyName())) {
                    values.add(item.getPropertyValue());
                } else if ("法术伤害".equals(item.getPropertyName())) {
                    values.add((int) (item.getPropertyValue() * 4.45));
                } else if ("治疗强度".equals(item.getPropertyName())) {
                    values.add((int) (item.getPropertyValue() * 2.775));
                }
            }

            int size = values.size();

            // list只有一个元素
            if (size == 1) {
                score.addAndGet(values.get(0));
            } else if (size > 1) { // 多条属性，对list排序，然后取最大值
                // 对list排序
                Collections.sort(values);

                // 取最后一个元素就是最大值
                score.addAndGet(values.get(size - 1));
            }
        } else if (EquipmentTypes.YIJIA.getValue().equals(type) || EquipmentTypes.YAODAI.getValue().equals(type)) { // 衣服/腰带
            for (AttributeVO item : list) {
                if ("物理防御".equals(item.getPropertyName())) {
                    score.addAndGet((int) (item.getPropertyValue() * 0.75));
                } else if ("气血".equals(item.getPropertyName())) {
                    score.addAndGet((int) (item.getPropertyValue() * 0.21));
                }
            }
        } else if (EquipmentTypes.TOU.getValue().equals(type)) { // 头盔/发钗
            for (AttributeVO item : list) {
                if ("物理防御".equals(item.getPropertyName())) {
                    score.addAndGet((int) (item.getPropertyValue() * 0.75));
                }
            }
        } else if (EquipmentTypes.XIANGLIAN.getValue().equals(type)) { // 项链
            for (AttributeVO item : list) {
                if ("法术伤害".equals(item.getPropertyName())) {
                    score.addAndGet((int) (item.getPropertyValue() * 1.5));
                } else if ("法术防御".equals(item.getPropertyName())) {
                    score.addAndGet((int) (item.getPropertyValue() * 0.75));
                }
            }
        } else if (EquipmentTypes.XIEZI.getValue().equals(type)) { // 鞋
            for (AttributeVO item : list) {
                if ("速度".equals(item.getPropertyName())) {
                    score.addAndGet((int) (item.getPropertyValue() * 1.5));
                } else if ("法术防御".equals(item.getPropertyName())) {
                    score.addAndGet((int) (item.getPropertyValue() * 0.75));
                }
            }
        } else {
            throw new GlobalException(ResponseCode.SERVER_ERROR, "非法参数：type = " + type);
        }

        return score.get();
    }

}